package bma.common.langutil.core;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 日期时间工具类
 * 
 * @author 关中
 * @since 1.0 (imported from BMA.ESP Project)
 */

public class DateTimeUtil {

	public static final long SECOND = 1000L;

	public static final long MINUTE = 60 * SECOND;

	public static final long HOUR = 60 * MINUTE;

	public static final long DAY = 24 * HOUR;

	public static String DATE_FORMAT = "yyyy-MM-dd";

	public static String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

	static public Date date(int y, int m, int d) {
		return date(y, m, d, 0, 0, 0);
	}

	static public Date date(int y, int m, int d, int h, int ms, int s) {
		Calendar cal = Calendar.getInstance();
		cal.set(y, m - 1, d, h, ms, s);
		return cal.getTime();
	}

	static public Date removeTime(Date d) {
		return setTime(d, 0, 0, 0);
	}

	static public Date setTime(Date d, int h, int m, int s) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(d);
		cal.set(Calendar.HOUR_OF_DAY, h);
		cal.set(Calendar.MINUTE, m);
		cal.set(Calendar.SECOND, s);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	static public String formatDate(String format, Date d) {
		if (d == null)
			return null;
		return new SimpleDateFormat(format).format(d);
	}

	static public String formatDate(Date d) {
		if (d == null)
			return null;
		return new SimpleDateFormat(DATE_FORMAT).format(d);
	}

	static public String formatDateTime(Date d) {
		if (d == null)
			return null;
		return new SimpleDateFormat(DATETIME_FORMAT).format(d);
	}

	public static String formatPeriod(long period) {

		if (period == 0)
			return "0s";

		StringBuffer buf = new StringBuffer(20);
		if (period < 0) {
			buf.append("-");
			period = -period;
		}

		long d;
		long r = period;

		d = r / DateTimeUtil.DAY;
		r = r % DateTimeUtil.DAY;
		if (d != 0) {
			buf.append(d).append("d");
		}

		d = r / DateTimeUtil.HOUR;
		r = r % DateTimeUtil.HOUR;
		if (d != 0) {
			buf.append(d).append("h");
		}

		d = r / DateTimeUtil.MINUTE;
		r = r % DateTimeUtil.MINUTE;
		if (d != 0) {
			buf.append(d).append("m");
		}

		d = r / DateTimeUtil.SECOND;
		r = r % DateTimeUtil.SECOND;
		if (d != 0 || r != 0) {
			buf.append(d);
			if (r != 0) {
				buf.append(".");
				if (r < 10)
					buf.append("0");
				if (r < 100)
					buf.append("0");
				buf.append(r);
			}
			buf.append("s");
		}

		return buf.toString();
	}

	public static Date setDate235959(Date date) {
		return setTime(date, 23, 59, 59);
	}

	static public Date parse(String v, String fm, Date def) {
		if (ValueUtil.empty(v))
			return def;
		try {
			return new SimpleDateFormat(fm).parse(v);
		} catch (Exception e) {
			return def;
		}
	}

	/**
	 * yyyy-MM-dd
	 */
	static public Date parseDate(String v, Date def) {
		return parse(v, "yyyy-MM-dd", def);
	}

	static public long parseDate(String v, long def) {
		Date r = parse(v, "yyyy-MM-dd", new Date(def));
		return r.getTime();
	}

	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	static public Date parseDateTime(String v, Date def) {
		return parse(v, "yyyy-MM-dd HH:mm:ss", def);
	}

	static public long parseDateTime(String v, long def) {
		Date r = parse(v, "yyyy-MM-dd HH:mm:ss", new Date(def));
		return r.getTime();
	}

	public static long parsePeriodValue(String value, long deflt) {
		if (ValueUtil.empty(value))
			return deflt;

		long sign = 1;
		long period = 0;

		int i = 0;
		int length = value.length();

		if (length > 0 && value.charAt(i) == '-') {
			sign = -1;
			i++;
		}

		while (i < length) {
			long delta = 0;
			char ch;

			for (; i < length && (ch = value.charAt(i)) >= '0' && ch <= '9'; i++) {
				delta = 10 * delta + ch - '0';
			}

			if (i >= length) {
				period += 1000 * delta;
			} else {
				switch (value.charAt(i++)) {
				case 's':
				case 'S':
					period += SECOND * delta;
					break;
				case 'M':
				case 'm':
					period += MINUTE * delta;
					break;
				case 'h':
				case 'H':
					period += HOUR * delta;
					break;
				case 'd':
				case 'D':
					period += DAY * delta;
					break;
				case 'w':
				case 'W':
					period += 7L * DAY * delta;
					break;
				default:
					return deflt;
				}
			}
		}
		return sign * period;
	}

	/**
	 * 得到一个星期的第一天的时间,默认这个星期的第一天为星期天 00:00:00
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfWeek(Date date) {
		return getFirstDayOfWeek(date, Calendar.SUNDAY);
	}

	/**
	 * 得到某一天的该星期的第一日 00:00:00
	 * 
	 * @param date
	 * @param firstDayOfWeek
	 *            一个星期的第一天为星期几
	 * 
	 * @return
	 */
	public static Date getFirstDayOfWeek(Date date, int firstDayOfWeek) {
		Calendar cal = Calendar.getInstance();
		if (date != null)
			cal.setTime(date);

		cal.setFirstDayOfWeek(firstDayOfWeek);
		cal.set(Calendar.DAY_OF_WEEK, firstDayOfWeek);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();

	}

	/**
	 * 得到一个星期的最后一日的时间,默认这个星期的第一天为星期天 00:00:00
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfWeek(Date date) {
		return getFirstDayOfWeek(date, Calendar.SUNDAY);
	}

	/**
	 * 得到指定日期相关的周的最后一日 00:00:00
	 * 
	 * @param date
	 * @param firstDayOfWeek
	 * @return
	 */
	public static Date getLastDayOfWeek(Date date, int firstDayOfWeek) {
		Calendar cal = Calendar.getInstance();
		if (date != null)
			cal.setTime(date);
		cal.setFirstDayOfWeek(firstDayOfWeek);
		cal.set(Calendar.DAY_OF_WEEK, firstDayOfWeek);
		cal.add(Calendar.DAY_OF_WEEK, 6);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();

	}

	/**
	 * 得到指定日期的在这个月的第一日. 00:00:00
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		if (date != null)
			cal.setTime(date);

		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		return cal.getTime();
	}

	/**
	 * 得到指定日期的相关月份的最后一日 00:00:00
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		if (date != null)
			cal.setTime(date);

		cal.set(Calendar.DAY_OF_MONTH,
				cal.getActualMaximum(Calendar.DAY_OF_MONTH));
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		return cal.getTime();
	}

	public static long currentUnixTimestamp() {
		return new GregorianCalendar().getTimeInMillis() / 1000;
	}

}